[toc]
awk BEGIN模式、END模式
1.BEGIN模式
BEGIN模式在awk程序执行后,但尚未执行处理动作之前需要做的工作(定义变量)
作用一 修改标题
//文件a.txt内容如下
101,abc,CEO
102,def,CTO
103,qaz,COO
//默认打印
[root@7-test1 ~]# awk '{print}' a.txt
101,abc,CEO
102,def,CTO
103,qaz,COO
//打印标题,注意ID、name必须用双引号
[root@7-test1 ~]# awk 'BEGIN{print "ID","name","position"}{print}' a.txt
ID name position
101,abc,CEO
102,def,CTO
103,qaz,COO
作用二 做运算
示例1:计算1到100的和
[root@7-test1 ~]# awk 'BEGIN{for(i=1;i<=100;i++) sum+=i;print sum}'
5050
示例2:普通计算
[root@7-test1 ~]# awk 'BEGIN{print 3+3}'
6
[root@7-test1 ~]# awk 'BEGIN{print 3*3}'
9
[root@7-test1 ~]# awk 'BEGIN{print 3-3}'
0
[root@7-test1 ~]# awk 'BEGIN{print 3**3}'
27
[root@7-test1 ~]# awk 'BEGIN{print 3%3}'
0
[root@7-test1 ~]# awk 'BEGIN{print 3/3}'
1
作用三 修改awk内置变量
record 字段
separator 分隔符
变量名 | 对应单词 | 含义 |
---|---|---|
FS | field separator | 字段分隔符,默认空格或tab |
OFS | output field separator | 输出分隔符,默认空格 |
RS | record separator | 记录分隔符,默认换行符\n |
ORS | output record separator | 输出记录分隔符 |
FS 指定字段分隔符
//passwd.txt文件内容如下
[root@7-test1 ~]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
示例1:以冒号为分隔符,打印文件第一列
//-F写法
[root@7-test1 ~]# awk -F: '{print $1}' passwd.txt
root
bin
daemon
//BEGIN {FS}写法
[root@7-test1 ~]# awk 'BEGIN{FS=":"}{print $1}' passwd.txt
root
bin
daemon
OFS 指定输出分隔符
//文件内容如下
[root@7-test1 ~]# cat a.txt
1 2 3
示例1:打印文件第一列和第三列,以冒号为分隔符
//-v OFS写法
[root@7-test1 ~]# awk -v OFS=: '{print $1,$3}' a.txt
1:3
//BEGIN {OFS}写法
[root@7-test1 ~]# awk 'BEGIN{OFS=":"}{print $1,$3}' a.txt
1:3
⚠️⚠️⚠️注意:!!!
-v OFS写法的一个坑:当print $0的时候,-v OFS会不生效
//正确输出应该为1:2:3
[root@7-test1 ~]# awk -v OFS=: '{print $0}' a.txt
1 2 3
解决方法
在print$0前加一个$1=$1
[root@7-test1 ~]# awk -v OFS=: '{$1=$1;print $0}' a.txt
1:2:3
RS 指定记录分隔符,即指定以什么为 分隔符,默认为\n
//文件内容
文件默认以换行为记录分隔符
[root@7-test1 ~]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
示例1:将文件的记录分隔符指定为/,即指定文件以/为换行符
//-v RS写法
[root@7-test1 ~]# awk -v RS=/ '{print $0}' passwd.txt
root:x:0:0:root:
root:
bin
bash
bin:x:1:1:bin:
bin:
sbin
nologin
//BEGIN {RS}写法
[root@7-test1 ~]# awk 'BEGIN{RS="/"}{print $0}' passwd.txt
root:x:0:0:root:
root:
bin
bash
bin:x:1:1:bin:
bin:
sbin
nologin
ORS 指定输出记录分隔符
//文件内容
[root@7-test1 ~]# cat a.txt
1
2
3
示例1:将文件的输出记录分隔符指定为/
//-v ORS写法
[root@7-test1 ~]# awk -v ORS="A" '{print $0}' a.txt
1A2A3A
//BEGIN {ORS}写法
[root@7-test1 ~]# awk 'BEGIN{ORS="A"}{print $0}' a.txt
1A2A3A
扩展-awk命令行参数
ARGC是命令行参数数量
ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始
ARGC
[root@test1 ~]# awk 'BEGIN{print ARGC}'
1
[root@test1 ~]# awk 'BEGIN{print ARGC}' 1 2
3
ARGV
[root@test1 ~]# awk 'BEGIN{print ARGV[0]}' 1 2
awk
[root@test1 ~]# awk 'BEGIN{print ARGV[1]}' 1 2
1
[root@test1 ~]# awk 'BEGIN{print ARGV[2]}' 1 2
2
2.END模式
END模式在awk读取完文件之后执行,主要作用为显示计算结果
作用 显示计算结果
示例1:统计/etc/passwd文件中前10行非登陆shell的个数
//文件内容
[root@7-test1 awk]# head -10 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
//统计文件中非登陆shell的个数,即统计/sbin/nologin的个数
[root@7-test1 awk]# head -10 /etc/passwd|awk '/nologin/{i++}END{print i}'
6
示例2:统计/etc/services中空行数量
[root@7-test1 awk]# awk '/^$/{i++}END{print i}' /etc/services
17
示例3:统计nginx访问日志中访问量前10的IP
[root@7-test1 ~]# awk '{a[$1]++}END{for(i in a) print a[i],i}' /var/log/nginx/access.log|sort -nr|head
275 109.98.109.101
262 146.196.97.242
210 47.52.155.218
152 142.234.200.81
75 72.211.58.142
10 120.25.208.128
7 42.236.10.84
6 42.236.10.92
3 5.188.210.12
3 42.236.10.75